package cn.youth996.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.youth996.config.properties.WechatProperties;
import cn.youth996.exception.ServiceException;
import cn.youth996.service.WeChatArticleService;
import cn.youth996.vo.article.SysArticleDetailVo;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.WxMpMassTagMessage;
import me.chanjar.weixin.mp.bean.draft.WxMpAddDraft;
import me.chanjar.weixin.mp.bean.draft.WxMpDraftArticles;
import me.chanjar.weixin.mp.bean.draft.WxMpDraftInfo;
import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult;
import me.chanjar.weixin.mp.bean.material.WxMpMaterial;
import me.chanjar.weixin.mp.bean.material.WxMpMaterialUploadResult;
import org.jsoup.Jsoup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 微信公众号文章服务实现类
 *
 * @author Zhan Xinjian
 * @date 2025/7/30
 */
@Slf4j
@Service
public class WeChatArticleServiceImpl implements WeChatArticleService {
    @Qualifier("wxMpArticleService")
    @Resource
    private WxMpService wxMpService;
    @Autowired
    private WechatProperties wechatProperties;

    /**
     * 通过第三方服务器上传
     * @param title 标题
     * @param content  内容
     * @param thumbnailUrl 封面图片
     */
    @Override
    public void addByThirdParty(String title, String content, String thumbnailUrl) {
        RestTemplate restTemplate = new RestTemplate();
        String url = wechatProperties.getUploadUrl();

        Map<String, Object> body = new HashMap<>();
        body.put("title", title);
        body.put("content", content);
        body.put("cover", thumbnailUrl);

        ResponseEntity<String> response = restTemplate.postForEntity(url, body, String.class);
        log.info(response.getBody());
    }


    @Override
    public String addDraft(String title, String content, String thumbnailUrl) throws WxErrorException, IOException {

        // 提取图片URL并替换
        List<String> imageUrls = extractImageUrls(content);
        for (String imgUrl : imageUrls) {
            String wechatUrl = uploadImage(imgUrl);
            content = content.replace(imgUrl, wechatUrl);
        }

        WxMpDraftArticles article = new WxMpDraftArticles();
        article.setAuthor("996码农之家");
        article.setContent(content);
        article.setTitle(title);
        article.setThumbMediaId(mediaUploadInImage(thumbnailUrl));
        // 可根据需求设置更多文章属性，如封面图片等

        WxMpAddDraft news = new WxMpAddDraft();
        news.setArticles(Collections.singletonList(article));

        return wxMpService.getDraftService().addDraft(news);
    }

    /**
     * 根据url上传永久素材
     *
     * @param url 图片url
     * @return 微信素材ID
     */
    public String mediaUploadInImage(String url) throws IOException, WxErrorException {
        byte[] bytes = this.downloadImage(url);
        File file = convert(bytes);
        String mediaId = materialFileUpload("image", file);
        FileUtil.del(file);
        return mediaId;
    }

    /**
     * 根据文件上传永久素材
     *
     * @param type 文件类型
     * @param file 文件
     * @return 微信素材ID
     */
    public String materialFileUpload(String type, File file) throws IOException, WxErrorException {
        WxMpMaterial wxMpMaterial = new WxMpMaterial();
        wxMpMaterial.setFile(file);
        WxMpMaterialUploadResult image = wxMpService.getMaterialService().materialFileUpload(type, wxMpMaterial);
        return image.getMediaId();
    }

    /**
     * 根据url上传图片
     * @param url 图片url
     * @return 微信可访问的url地址
     */
    public String uploadImage(String url) throws IOException, WxErrorException {
        byte[] bytes = this.downloadImage(url);
        //bytes转成file
        File file = convert(bytes);
        WxMediaImgUploadResult wxMediaImgUploadResult = wxMpService.getMaterialService().mediaImgUpload(file);
        FileUtil.del(file);
        return wxMediaImgUploadResult.getUrl();
    }

    /**
     * byte[] 转 File
     *
     * @param bytes
     * @return
     * @throws IOException
     */
    public static File convert(byte[] bytes) throws IOException {
        // 创建一个临时文件
        File tempFile = File.createTempFile("temp-", ".png");
        // 使用 FileOutputStream 将字节数组写入文件
        try (FileOutputStream fos = new FileOutputStream(tempFile)) {
            fos.write(bytes);
        }
        return tempFile;
    }

    /**
     * 下载图片
     *
     * @param url
     * @return
     */
    private byte[] downloadImage(String url) {
        return new RestTemplate().getForObject(url, byte[].class);
    }

    /**
     * 提取 HTML 中的图片 URL
     */
    private List<String> extractImageUrls(String html) {
        org.jsoup.nodes.Document doc = Jsoup.parse(html);
        return doc.select("img").stream()
                .map(img -> img.attr("src"))
                .collect(Collectors.toList());
    }

    @Override
    public void wechatSendAll(String mediaId) {
        try {
            WxMpDraftInfo draft = wxMpService.getDraftService().getDraft(mediaId);
            if (draft == null || draft.getNewsItem() == null || draft.getNewsItem().isEmpty()) {
                throw new ServiceException("无效的mediaId: " + mediaId);
            }
            WxMpMassTagMessage wxMpMassTagMessage = new WxMpMassTagMessage();
            wxMpMassTagMessage.setMediaId(mediaId);
            wxMpMassTagMessage.setMsgType("mpnews");
            wxMpMassTagMessage.setSendAll(true);
            wxMpMassTagMessage.setSendIgnoreReprint(true);
            wxMpService.getMassMessageService().massGroupMessageSend(wxMpMassTagMessage);
        } catch (WxErrorException e) {
            log.error("微信群发失败", e);
            throw new RuntimeException(e);
        }

    }

    @Override
    public void add(SysArticleDetailVo sysArticle) throws IOException, WxErrorException {
        addDraft(sysArticle.getTitle(), sysArticle.getContent(), sysArticle.getCover());
    }
}
